package org.zjvis.datascience.service;

import lombok.Data;
import org.zjvis.datascience.common.dto.ActionDTO;

import java.util.List;
import java.util.Stack;

/**
 * @description 双stack模拟redo和undo
 * @date 2021-07-21
 */
@Data
public class ActionDeStack {
    // redo或者undo最大执行次数
    private static final Long MAX_TIMES = 4L;

    private Long pipelineId;

    private Stack<ActionDTO> undoStack;

    private Stack<ActionDTO> redoStack;

    public ActionDeStack(Long pipelineId) {
        this.pipelineId = pipelineId;
        undoStack = new Stack<>();
        redoStack = new Stack<>();
    }

    /**
     * 从undoStack弹出item入队到redoStack，返回item
     *
     * @return
     */
    public synchronized ActionDTO undo() {
        if (undoStack.isEmpty()) {
            return null;
        }
        ActionDTO item = undoStack.pop();
        redoStack.push(item);
        return item;
    }

    /**
     * 从redoStack弹出item，入队到undoStack
     *
     * @return
     */
    public synchronized ActionDTO redo() {
        if (redoStack.isEmpty()) {
            return null;
        }
        ActionDTO item = redoStack.pop();
        undoStack.push(item);
        return item;
    }

    /**
     * @param actionService
     * @return
     */
    public synchronized boolean initUndoStack(ActionService actionService) {
        //List<ActionDTO> actions = actionService.queryLatestActionByProjectId(projectId, MAX_TIMES * 10);
        List<ActionDTO> actions = actionService.queryLatestActionByPipelineId(pipelineId, MAX_TIMES * 10);
        ;
//        int index = actions.size() - 1;

        undoStack.addAll(actions);
//        for (; index >= 0 && actions.size() < MAX_TIMES;  --index) {
//            ActionDTO item = actions.get(index);
//            if (redoStack.contains(item)) {
//                continue;
//            }
//            undoStack.push(item);
//        }
        return true;
    }

    /**
     * 如果在redo和undo的过程中，有做增删改操作，需要去重新更新下undoStack
     *
     * @param actionService
     * @return
     */
    public synchronized boolean resizeUndoStack(ActionService actionService) {
        undoStack.clear();
        return initUndoStack(actionService);
    }

    /**
     * 插入数据到undoStack
     *
     * @param action
     * @return
     */
    public synchronized boolean addUndoStack(ActionDTO action) {
        undoStack.push(action);
        return true;
    }

    /**
     * 清空redoStack
     *
     * @return
     */
    public synchronized boolean clearRedoStack() {
        redoStack.clear();
        return true;
    }

    /**
     * 撤销栈是否超过限制条数
     *
     * @return
     */
    public int outLimit() {
        return (int) (undoStack.size() - MAX_TIMES);
    }

    /**
     * 移除栈中废弃的一个
     *
     * @return
     */
    public ActionDTO removeUndoStack() {
        return undoStack.remove(0);
    }

    public int redoStackSize() {
        return redoStack.size();
    }

    public ActionDTO removeRedoStack() {
        return redoStack.remove(0);
    }
}